﻿// 版权所有 (C) Microsoft Corporation。保留所有权利。

// DeclarativeSecurity.cs
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;

class NativeMethods
{
    // 这是对非托管代码的调用。执行此方法需要
    // UnmanagedCode 安全权限。如果没有此权限，
    // 则调用此方法的尝试将引发 SecurityException：
    [DllImport("msvcrt.dll")]
    public static extern int puts(string str);
    [DllImport("msvcrt.dll")]
    internal static extern int _flushall();
}

class MainClass
{
    // 附加到此方法的安全权限在调用此方法
    // 期间将拒绝当前权限集中的
    // UnmanagedCode 权限：
    // 即使 CallUnmanagedCodeWithoutPermission 方法是在
    // 已经为非托管代码调用了 Assert 的堆栈帧中调用的，
    // 也无法调用本机代码。
    // 由于此函数附加了非托管代码的 Deny 权限，
    // 因此相应的安全权限被覆盖。
    [SecurityPermission(SecurityAction.Deny, Flags = 
       SecurityPermissionFlag.UnmanagedCode)]
    private static void CallUnmanagedCodeWithoutPermission()
    {
        try
        {
            Console.WriteLine("Attempting to call unmanaged code without permission.");
            NativeMethods.puts("Hello World!");
            NativeMethods._flushall();
            Console.WriteLine("Called unmanaged code without permission. Whoops!");
        }
        catch (SecurityException)
        {
            Console.WriteLine("Caught Security Exception attempting to call unmanaged code.");
        }
    }

    // 每当调用此方法时，附加到此方法的安全权限都强制
    // 对非托管代码权限进行
    // 运行时检查。如果调用方不具有非托管代码
    // 的访问权限，则调用将产生安全异常。
    // 即使 CallUnmanagedCodeWithPermission 方法是在
    // 已经为非托管代码调用了
    //  Deny 的堆栈帧中调用的，也不会妨碍您调用
    // 本机代码。由于此方法附加了非托管代码的 Assert
    // 权限，因此相应的安全权限被覆盖。
    [SecurityPermission(SecurityAction.Assert, Flags = 
       SecurityPermissionFlag.UnmanagedCode)]
    private static void CallUnmanagedCodeWithPermission()
    {
        try
        {
            Console.WriteLine("Attempting to call unmanaged code with permission.");
            NativeMethods.puts("Hello World!");
            NativeMethods._flushall();
            Console.WriteLine("Called unmanaged code with permission.");
        }
        catch (SecurityException)
        {
            Console.WriteLine("Caught Security Exception attempting to call unmanaged code. Whoops!");
        }
    }

    public static void Main() 
    {
        SecurityPermission perm = new
            SecurityPermission(SecurityPermissionFlag.UnmanagedCode);

        // 此方法本身附加了非托管代码
        // 的 Deny 安全权限，这会重写
        // 此堆栈帧中的 Assert 权限。
        perm.Assert();
        CallUnmanagedCodeWithoutPermission();

        // 此方法本身附加了非托管代码
        // 的安全权限 Assert，这会重写 
        // 此堆栈帧中的 Deny 权限。
        perm.Deny();
        CallUnmanagedCodeWithPermission();
    }
}

